package com.tangsm.spring.boot.strategy.order.context;

import com.tangsm.spring.boot.strategy.order.annotation.OrderAnnotation;
import com.tangsm.spring.boot.strategy.order.service.OrderService;
import org.reflections.Reflections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 策略上下文（策略接口的持有者）
 * <pre>
 * Maven依赖：reflections 反射工具包
 * <dependency>
 *     <groupId>org.reflections</groupId>
 *     <artifactId>reflections</artifactId>
 *     <version>0.10.2</version>
 * </dependency>
 * </pre>
 *
 * @author tangsm
 */
public class OrderContext {
    private static final Logger log = LoggerFactory.getLogger(OrderContext.class);

    private static Map<String, Class<?>> allActions;
    private static final String PACKAGE_NAME = "com.tangsm.strategy.java.annotation";

    private OrderService orderService;

    static {
        // reflections 反射工具包
        Reflections reflections = new Reflections(PACKAGE_NAME);

        // 扫描有OrderAnnotation注解的类
        Set<Class<?>> annotationClasses = reflections.getTypesAnnotatedWith(OrderAnnotation.class);

        // 缓存获取到的实例
        allActions = new ConcurrentHashMap<>();
        for (Class<?> classObject : annotationClasses) {
            // 获取类注解
            OrderAnnotation annotation = classObject.getAnnotation(OrderAnnotation.class);

            // 根据注解枚举缓存实例
            allActions.put(annotation.name().getCode(), classObject);
        }

        // 返回指定映射的不可修改视图。
        allActions = Collections.unmodifiableMap(allActions);
    }

    /**
     * 创建订单实例
     * @param name 订单类型名称
     */
    public OrderContext(String name) {
        if (allActions.containsKey(name)) {
            log.info("创建订单实例，类型名称：{}", name);
            try {
                orderService = (OrderService) allActions.get(name).newInstance();
            } catch (InstantiationException | IllegalAccessException e) {
                log.error("创建订单实例异常，类型名称：{}", name, e);
            }
        } else {
            log.warn("创建订单实例失败，{}，类型名称找不到", name);
        }
    }

    /**
     * 下单
     *
     * @param amount 订单金额
     * @return 响应结果
     */
    public String placeOrder(BigDecimal amount) {
        if (orderService == null) {
            log.warn("下单失败，订单类型不存在");
            return "下单失败，订单类型不存在";
        }

        return orderService.placeOrder(amount);
    }
}
